<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';

import { useSortable } from '@vben/hooks';
import { useTableSortStore } from '@vben/stores';

import { ElTable, ElTableColumn, ElTooltip } from 'element-plus';

import RaiseStatus from '#/components/raiseStatus.vue';
import { transNullTarget } from '#/utils/reportTools';

const props = defineProps<{
  columnOrder: any;
  loading?: boolean;
  methods: any;
  summaryMethod?: (param: any) => any[];
  tableData: any[];
}>();

const emits = defineEmits<{
  (e: 'update:columnOrder', val: typeof props.columnOrder): void;
  (e: 'sortChange', sort: { order: string; prop: string }): void;
}>();

const getTableInstance = () => {
  return tableRef.value;
};

const tableSortStore = useTableSortStore();

defineExpose({
  getTableInstance,
});

const tableRef = ref<any>(null);
const sortableInstance = ref<any>(null);

// 初始化表头拖拽
const initTableHeaderDrag = async () => {
  await nextTick();
  if (sortableInstance.value) {
    sortableInstance.value.destroy();
    sortableInstance.value = null;
  }
  const headerRow = tableRef.value?.$el.querySelector(
    '.el-table__header-wrapper .el-table__header thead tr',
  );

  if (headerRow) {
    try {
      const { initializeSortable } = useSortable(headerRow, {
        animation: 150,
        ghostClass: 'sortable-ghost',
        chosenClass: 'sortable-chosen',
        dragClass: 'sortable-drag',
        filter: '.el-table__column-resize-proxy, .el-table__fixed-right-patch',
        onEnd: (evt: any) => {
          const { newIndex, oldIndex } = evt;
          if (
            newIndex !== oldIndex &&
            newIndex !== undefined &&
            oldIndex !== undefined
          ) {
            // eslint-disable-next-line vue/no-mutating-props
            const moved = props.columnOrder.splice(oldIndex, 1)[0];
            if (moved) {
              // eslint-disable-next-line vue/no-mutating-props
              props.columnOrder.splice(newIndex, 0, moved);
              tableSortStore.setSortField(props.columnOrder);
              emits('update:columnOrder', [...props.columnOrder]);
            }
          }
        },
      });

      sortableInstance.value = await initializeSortable();
    } catch (error) {
      console.warn('Failed to initialize header drag:', error);
    }
  }
};

onMounted(() => {
  const sortField = tableSortStore.getSortField();
  if (
    sortField &&
    JSON.stringify(sortField) !== '{}' &&
    checkPropsInArrays(sortField, props.columnOrder, 'prop')
  ) {
    emits('update:columnOrder', [...sortField]);
  } else {
    tableSortStore.clearSortField();
  }
  initTableHeaderDrag();
});
onUnmounted(() => {
  if (sortableInstance.value) {
    sortableInstance.value.destroy();
  }
});
watch(
  () => props.tableData,
  async () => {
    await nextTick();
    initTableHeaderDrag();
  },
  { flush: 'post' },
);

const click7 = (click: string, row: any) => {
  props.methods[click](row);
};

/**
 * 检查数组A中每个对象的prop属性值是否都存在于数组B对应对象的prop属性中，且数组长度相等
 * @param {Array} arrayA - 第一个对象数组
 * @param {Array} arrayB - 第二个对象数组
 * @param {string} prop - 要比较的属性名
 * @returns {boolean} - 如果满足条件返回true，否则返回false
 */
function checkPropsInArrays(arrayA: any, arrayB: any, prop: string) {
  // 检查数组长度是否相等
  if (arrayA.length !== arrayB.length) {
    return false;
  }

  // 获取数组B中所有prop属性的值
  const propValuesInB = new Set(arrayB.map((item: any) => item[prop]));

  // 检查数组A中每个项的prop属性值是否都在数组B的prop属性值中
  return arrayA.every((itemA: any) => propValuesInB.has(itemA[prop]));
}
</script>

<template>
  <ElTable
    :data="tableData"
    border
    ref="tableRef"
    :summary-method="summaryMethod"
    show-summary
    v-loading="loading"
    @sort-change="(e) => emits('sortChange', e)"
  >
    <ElTableColumn
      v-for="column in columnOrder"
      :key="column.prop"
      :prop="column.prop"
      :label="column.label"
      :min-width="column.minWidth"
      :sortable="column.sortable || 'custom'"
      header-align="center"
    >
      <template #header v-if="column.tooltip">
        <span>
          <ElTooltip class="item" effect="dark" placement="top-start">
            <span class="cursor-pointer">
              {{ column.label }}
            </span>
            <template #content>
              <div style="width: auto">{{ column.tooltip }}</div>
            </template>
          </ElTooltip>
        </span>
      </template>

      <template #default="scope">
        <!-- 供应商名称列 -->
        <template v-if="column.showOne">
          <div
            class="text-align-right hover-supplier cursor-pointer !justify-start"
            @click="click7(column.click, scope.row)"
          >
            {{ transNullTarget(scope.row.cPublisherName) }}
          </div>
        </template>

        <!-- 其他列的统一模板 -->
        <template v-else>
          <div class="text-align-right">
            {{
              transNullTarget(
                scope.row[column.prop],
                !column.prop.includes('Num'),
              )
            }}
          </div>
          <RaiseStatus
            :r1="+scope.row[column.prop]"
            :r2="+scope.row[column.prop.replace('c', 'l')]"
          />
          <div class="text-align-right">
            {{
              transNullTarget(
                scope.row[column.prop.replace('c', 'l')],
                !column.prop.includes('Num'),
              )
            }}
          </div>
        </template>
      </template>
    </ElTableColumn>
  </ElTable>
</template>

<style scoped>
.text-right {
  @apply flex items-center justify-end;
}

.sortable-ghost {
  background: #f0f0f0 !important;
  opacity: 0.5;
}

.sortable-chosen {
  background: #e6f7ff !important;
  border-color: #1890ff !important;
}

.sortable-drag {
  z-index: 1000;
  box-shadow: 0 4px 8px rgb(0 0 0 / 10%);
  opacity: 0.8;
  transform: rotate(2deg);
}
</style>
